home *** CD-ROM | disk | FTP | other *** search
/ Practical Algorithms for Image Analysis / Practical Algorithms for Image Analysis.iso / LIBIP / PCCFCT.C < prev    next >
C/C++ Source or Header  |  1999-09-11  |  20KB  |  707 lines

  1. /* 
  2.  * pccft.c
  3.  * 
  4.  * Practical Algorithms for Image Analysis
  5.  * 
  6.  * Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
  7.  */
  8.  
  9. /* PCCFCT:      functions for PCC encoding
  10.  *            (decoding functions in PCCFCTDE; and functions common
  11.  *              to both encoding and decoding programs in PCCFCT2)
  12.  *      FUNCTIONS:
  13.  *              PCCCODES, PCCCODE, PCCTRACK, PCCRSTORE, PCCLSTORE, PCCFSTORE,
  14.  *              PCCWRITE
  15.  */
  16.  
  17. #include <stdio.h>
  18. #include "pcc2.h"               /* header file for PCC programs */
  19.  
  20. struct code code;               /* structure contains codes for 
  21.                                  * * direction sequences and features */
  22. extern unsigned char *fcCode;   /* code storage */
  23. extern int nByteCode;           /* no. bytes in storage */
  24.  
  25.  
  26. /* PCCCODES:    function constructs table of PCC codes
  27.  *            corresponding to sequences of 0, 1, 2, or 3
  28.  *              direction vectors and features endpoint, bifurcation,
  29.  *              and cross
  30.  *                      usage: pcccodes ()
  31.  *                              extern int decode;
  32.  *
  33.  */
  34.  
  35. pcccodes ()
  36. {
  37. /* DIRECTION SEGMENTS TO CODE TABLES */
  38.  
  39. /* 0-vector chains */
  40.   code.code0[00] = 193;
  41.  
  42. /* 1-vector chains */
  43.   code.code1[00] = 194;
  44.   code.code1[01] = 195;
  45.   code.code1[02] = 196;
  46.   code.code1[03] = 197;
  47.   code.code1[04] = 198;
  48.   code.code1[05] = 199;
  49.   code.code1[06] = 200;
  50.   code.code1[07] = 201;
  51.  
  52. /* 2-vector chains */
  53.   code.code2[00] = 202;
  54.   code.code2[010] = 203;
  55.   code.code2[020] = 204;
  56.   code.code2[060] = 205;
  57.   code.code2[070] = 206;
  58.   code.code2[001] = 207;
  59.   code.code2[011] = 208;
  60.   code.code2[021] = 209;
  61.   code.code2[031] = 210;
  62.   code.code2[071] = 211;
  63.   code.code2[002] = 212;
  64.   code.code2[012] = 213;
  65.   code.code2[022] = 214;
  66.   code.code2[032] = 215;
  67.   code.code2[042] = 216;
  68.   code.code2[013] = 217;
  69.   code.code2[023] = 218;
  70.   code.code2[033] = 219;
  71.   code.code2[043] = 220;
  72.   code.code2[053] = 221;
  73.   code.code2[024] = 222;
  74.   code.code2[034] = 223;
  75.   code.code2[044] = 224;
  76.   code.code2[054] = 225;
  77.   code.code2[064] = 226;
  78.   code.code2[035] = 227;
  79.   code.code2[045] = 228;
  80.   code.code2[055] = 229;
  81.   code.code2[065] = 230;
  82.   code.code2[075] = 231;
  83.   code.code2[006] = 232;
  84.   code.code2[046] = 233;        /* oops -- this was 333 before */
  85.   code.code2[056] = 234;
  86.   code.code2[066] = 235;
  87.   code.code2[076] = 236;
  88.   code.code2[007] = 237;
  89.   code.code2[017] = 238;
  90.   code.code2[057] = 239;
  91.   code.code2[067] = 240;
  92.   code.code2[077] = 241;
  93.  
  94. /* 3-vector chains */
  95.   code.code3[0000] = 1;
  96.   code.code3[0100] = 2;
  97.   code.code3[0200] = 3;
  98.   code.code3[0600] = 4;
  99.   code.code3[0700] = 5;
  100.   code.code3[0010] = 6;
  101.   code.code3[0110] = 7;
  102.   code.code3[0210] = 8;
  103.   code.code3[0310] = 9;
  104.   code.code3[0710] = 10;
  105.   code.code3[0020] = 11;
  106.   code.code3[0120] = 12;
  107.   code.code3[0220] = 13;
  108.   code.code3[0320] = 14;
  109.   code.code3[0060] = 15;
  110.   code.code3[0560] = 16;
  111.   code.code3[0660] = 17;
  112.   code.code3[0760] = 18;
  113.   code.code3[0070] = 19;
  114.   code.code3[0170] = 20;
  115.   code.code3[0570] = 21;
  116.   code.code3[0670] = 22;
  117.   code.code3[0770] = 23;
  118.   code.code3[0001] = 24;
  119.   code.code3[0201] = 25;
  120.   code.code3[0101] = 26;
  121.   code.code3[0601] = 27;
  122.   code.code3[0701] = 28;
  123.   code.code3[0011] = 29;
  124.   code.code3[0111] = 30;
  125.   code.code3[0211] = 31;
  126.   code.code3[0311] = 32;
  127.   code.code3[0711] = 33;
  128.   code.code3[0021] = 34;
  129.   code.code3[0121] = 35;
  130.   code.code3[0221] = 36;
  131.   code.code3[0321] = 37;
  132.   code.code3[0421] = 38;
  133.   code.code3[0131] = 39;
  134.   code.code3[0231] = 40;
  135.   code.code3[0331] = 41;
  136.   code.code3[0431] = 42;
  137.   code.code3[0531] = 43;
  138.   code.code3[0071] = 44;
  139.   code.code3[0171] = 45;
  140.   code.code3[0571] = 46;
  141.   code.code3[0671] = 47;
  142.   code.code3[0771] = 48;
  143.   code.code3[0002] = 49;
  144.   code.code3[0102] = 50;
  145.   code.code3[0202] = 51;
  146.   code.code3[0702] = 52;
  147.   code.code3[0012] = 53;
  148.   code.code3[0112] = 54;
  149.   code.code3[0212] = 55;
  150.   code.code3[0312] = 56;
  151.   code.code3[0712] = 57;
  152.   code.code3[0022] = 58;
  153.   code.code3[0122] = 59;
  154.   code.code3[0222] = 60;
  155.   code.code3[0322] = 61;
  156.   code.code3[0422] = 62;
  157.   code.code3[0132] = 63;
  158.   code.code3[0232] = 64;
  159.   code.code3[0332] = 65;
  160.   code.code3[0432] = 66;
  161.   code.code3[0532] = 67;
  162.   code.code3[0242] = 68;
  163.   code.code3[0342] = 69;
  164.   code.code3[0442] = 70;
  165.   code.code3[0542] = 71;
  166.   code.code3[0013] = 72;
  167.   code.code3[0113] = 73;
  168.   code.code3[0213] = 74;
  169.   code.code3[0313] = 75;
  170.   code.code3[0713] = 76;
  171.   code.code3[0023] = 77;
  172.   code.code3[0123] = 78;
  173.   code.code3[0223] = 79;
  174.   code.code3[0323] = 80;
  175.   code.code3[0423] = 81;
  176.   code.code3[0133] = 82;
  177.   code.code3[0233] = 83;
  178.   code.code3[0333] = 84;
  179.   code.code3[0433] = 85;
  180.   code.code3[0533] = 86;
  181.   code.code3[0243] = 87;
  182.   code.code3[0343] = 88;
  183.   code.code3[0443] = 89;
  184.   code.code3[0543] = 90;
  185.   code.code3[0643] = 91;
  186.   code.code3[0353] = 92;
  187.   code.code3[0453] = 93;
  188.   code.code3[0553] = 94;
  189.   code.code3[0653] = 95;
  190.   code.code3[0753] = 96;
  191.   code.code3[0124] = 97;
  192.   code.code3[0224] = 98;
  193.   code.code3[0324] = 99;
  194.   code.code3[0424] = 100;
  195.   code.code3[0134] = 101;
  196.   code.code3[0234] = 102;
  197.   code.code3[0334] = 103;
  198.   code.code3[0434] = 104;
  199.   code.code3[0534] = 105;
  200.   code.code3[0244] = 106;
  201.   code.code3[0344] = 107;
  202.   code.code3[0444] = 108;
  203.   code.code3[0544] = 109;
  204.   code.code3[0644] = 110;
  205.   code.code3[0354] = 111;
  206.   code.code3[0454] = 112;
  207.   code.code3[0554] = 113;
  208.   code.code3[0654] = 114;
  209.   code.code3[0754] = 115;
  210.   code.code3[0464] = 116;
  211.   code.code3[0564] = 117;
  212.   code.code3[0664] = 118;
  213.   code.code3[0764] = 119;
  214.   code.code3[0135] = 120;
  215.   code.code3[0235] = 121;
  216.   code.code3[0335] = 122;
  217.   code.code3[0435] = 123;
  218.   code.code3[0535] = 124;
  219.   code.code3[0245] = 125;
  220.   code.code3[0345] = 126;
  221.   code.code3[0445] = 127;
  222.   code.code3[0545] = 128;
  223.   code.code3[0645] = 129;
  224.   code.code3[0355] = 130;
  225.   code.code3[0455] = 131;
  226.   code.code3[0555] = 132;
  227.   code.code3[0655] = 133;
  228.   code.code3[0755] = 134;
  229.   code.code3[0065] = 135;
  230.   code.code3[0465] = 136;
  231.   code.code3[0565] = 137;
  232.   code.code3[0665] = 138;
  233.   code.code3[0765] = 139;
  234.   code.code3[0075] = 140;
  235.   code.code3[0175] = 141;
  236.   code.code3[0575] = 142;
  237.   code.code3[0675] = 143;
  238.   code.code3[0775] = 144;
  239.   code.code3[0006] = 145;
  240.   code.code3[0106] = 146;
  241.   code.code3[0606] = 147;
  242.   code.code3[0706] = 148;
  243.   code.code3[0346] = 149;
  244.   code.code3[0446] = 150;
  245.   code.code3[0546] = 151;
  246.   code.code3[0646] = 152;
  247.   code.code3[0356] = 153;
  248.   code.code3[0456] = 154;
  249.   code.code3[0556] = 155;
  250.   code.code3[0656] = 156;
  251.   code.code3[0756] = 157;
  252.   code.code3[0066] = 158;
  253.   code.code3[0466] = 159;
  254.   code.code3[0566] = 160;
  255.   code.code3[0666] = 161;
  256.   code.code3[0766] = 162;
  257.   code.code3[0076] = 163;
  258.   code.code3[0176] = 164;
  259.   code.code3[0576] = 165;
  260.   code.code3[0676] = 166;
  261.   code.code3[0776] = 167;
  262.   code.code3[0007] = 168;
  263.   code.code3[0107] = 169;
  264.   code.code3[0207] = 170;
  265.   code.code3[0607] = 171;
  266.   code.code3[0707] = 172;
  267.   code.code3[0017] = 173;
  268.   code.code3[0117] = 174;
  269.   code.code3[0217] = 175;
  270.   code.code3[0317] = 176;
  271.   code.code3[0717] = 177;
  272.   code.code3[0357] = 178;
  273.   code.code3[0457] = 179;
  274.   code.code3[0557] = 180;
  275.   code.code3[0657] = 181;
  276.   code.code3[0757] = 182;
  277.   code.code3[0067] = 183;
  278.   code.code3[0467] = 184;
  279.   code.code3[0567] = 185;
  280.   code.code3[0667] = 186;
  281.   code.code3[0767] = 187;
  282.   code.code3[0077] = 188;
  283.   code.code3[0177] = 189;
  284.   code.code3[0577] = 190;
  285.   code.code3[0677] = 191;
  286.   code.code3[0777] = 192;
  287.  
  288. /* feature codes */
  289.   code.codeFeat[0] = STOPCODE;
  290.   code.codeFeat[1] = ENDCODE;
  291.   code.codeFeat[2] = LINECODE;
  292.   code.codeFeat[3] = BIFCODE;
  293.   code.codeFeat[4] = CROSSCODE;
  294.   code.codeFeat[5] = STARTCODE;
  295.   code.codeFeat[6] = LINEBRCODE;
  296.   code.codeFeat[7] = BIFBRCODE;
  297.   code.codeFeat[8] = CROSSBRCODE;
  298.  
  299.   return (0);
  300. }
  301.  
  302.  
  303. /* PCCODE:      function performs PCC coding on thin line image
  304.  *                    usage: pccode (image, nX, nY)
  305.  *
  306.  */
  307.  
  308. #define E 3                     /* neighborhood pixel in E dirn */
  309. #define SE 4                    /* neighborhood pixel in SE dirn */
  310. #define S 5                     /* neighborhood pixel in S dirn */
  311.  
  312. pcccode (image, nX, nY)
  313.      unsigned char **image;     /* image region to be coded */
  314.      long nX, nY;               /* image region size */
  315. {
  316.   register long x, y,           /* image coordinates */
  317.     nXm1, nYm1;                 /* x-width minus 1 */
  318.   long direction,               /* direction from center of current pt */
  319.     xTrack, yTrack,             /* tracking coordinates */
  320.     chain,                      /* flag = 1 to chain code, 0 to stop */
  321.     nFeature;                   /* no. emanations from center pt. */
  322.   long nDirns,                  /* no. dirn.s in current feature */
  323.     dirns[NDIRNSPERFEATURE],    /* array of dirns per feature */
  324.     junctionFlag;               /* see note above (21-Mar-85) */
  325.   long branchNMax;              /* diagnostic to monitor max branch no. */
  326.   struct branch1 *branch;       /* stack of branches */
  327.   struct branch1 branchTop;     /* first branch */
  328.   long nBranch;                 /* no. of branches in stack */
  329.   long i;
  330.   long Xmax = 0;
  331.   long Ymax = 0;
  332.  
  333. /* initialize */
  334.   nXm1 = nX - 1;
  335.   nYm1 = nY - 1;
  336.   junctionFlag = 0;
  337.   branch = &branchTop;
  338.   branch->previous = branch;
  339.  
  340. /* zero 3 pixel boundary on analysis region */
  341.   for (y = 0; y < nY; y++) {
  342.     image[y][0] = image[y][nXm1] = IMGOFF;
  343.     image[y][1] = image[y][nXm1 - 1] = IMGOFF;
  344.     image[y][2] = image[y][nXm1 - 2] = IMGOFF;
  345.   }
  346.   for (x = 1; x < nXm1; x++) {
  347.     image[0][x] = image[nYm1][x] = IMGOFF;
  348.     image[1][x] = image[nYm1 - 1][x] = IMGOFF;
  349.     image[2][x] = image[nYm1 - 2][x] = IMGOFF;
  350.   }
  351.  
  352. /* sequentially search for ON point, and when found perform
  353.  * feature chain coding */
  354.  
  355.   chain = nBranch = branchNMax = nDirns = 0;
  356.  
  357.   xTrack = 0;
  358.   yTrack = 0;
  359.   for (y = 1; y < nYm1; y++) {
  360.     for (x = 1; x < nXm1; x++) {
  361.       if (xTrack > Xmax)
  362.         Xmax = xTrack;
  363.       if (yTrack > Ymax)
  364.         Ymax = yTrack;
  365.       if (image[y][x] == IMGON) {
  366.         direction = SE;
  367.         chain = 1;
  368.         xTrack = x;
  369.         yTrack = y;
  370.  
  371.         /* check if first feature is start code or line break code */
  372.         if ((image[y - 1][x] + image[y - 1][x + 1]
  373.              + image[y][x + 1] + image[y + 1][x + 1]
  374.              + image[y + 1][x] + image[y + 1][x - 1]
  375.              + image[y][x - 1] + image[y - 1][x - 1])
  376.             > IMGON) {
  377.           pccbranch (&branch, xTrack, yTrack, S);
  378.           nBranch++;
  379.           direction = E;        /* so PCCTRACK finds only 1 branch */
  380.           image[y][x] = ERASED; /* set break node to ERASED */
  381.  
  382.           pccrstore (NLINEBRCODE, xTrack, yTrack);
  383.         }
  384.         else {
  385.           /* printf ("\nstart chain x=%ld, y=%ld\n", xTrack, yTrack); */
  386.           pccrstore (NSTARTCODE, xTrack, yTrack);
  387.         }
  388.  
  389.         while (chain) {
  390.  
  391.           nFeature = pcctrack (image, &xTrack, &yTrack,
  392.                                &direction, &branch, &nBranch);
  393.  
  394.           if (nBranch > branchNMax)
  395.             branchNMax = nBranch;
  396.  
  397.           /* immediately after cross, TLC1TRACK will call the
  398.            * two remaining branches of the cross a bifurcation
  399.            * (unless cross contains loop); correct for this */
  400.           if (junctionFlag == 1) {
  401.             if (nFeature > 1) {
  402.               for (i = nFeature - 1; i > 0; --i) {
  403.                 --nBranch;
  404.                 branch = branch->previous;
  405.               }
  406.               nFeature = 1;
  407.             }
  408.             junctionFlag = 0;
  409.           }
  410.  
  411.           /* depending on feature (or no. of emanations) from
  412.            * center, do following */
  413.  
  414.           switch (nFeature) {
  415.             /* if hit endpoint, store it and pop next branch */
  416.           case 0:
  417.  
  418.             pcclstore (dirns, nDirns);
  419.             nDirns = 0;
  420.  
  421.             pccfstore (NENDCODE);
  422.  
  423.             if (branch->previous != branch) {
  424.               branch = branch->previous;
  425.               nBranch--;
  426.               xTrack = branch->x;
  427.               yTrack = branch->y;
  428.               direction = branch->variable;
  429.               junctionFlag = 1;
  430.             }
  431.             else {
  432.               chain = 0;
  433.               /* printf ("\nchain=0 at x=%ld, y=%ld\n", xTrack, yTrack); */
  434.             }
  435.             break;
  436.  
  437.             /* if not feature, then temporarily store direction of
  438.              * new point and after NDIRNSPERFEATURE, store feature */
  439.           case 1:
  440.             dirns[nDirns++] = direction;
  441.  
  442.             if (nDirns == NDIRNSPERFEATURE) {
  443.               pcclstore (dirns, nDirns);
  444.               nDirns = 0;
  445.             }
  446.             break;
  447.  
  448.             /* if hit other feature (bifirc., cross), store it
  449.              * and continue on */
  450.  
  451.           case 2:
  452.             pcclstore (dirns, nDirns);
  453.             nDirns = 0;
  454.             pccfstore (NBIFCODE);
  455.  
  456.             dirns[nDirns++] = direction;
  457.             break;
  458.  
  459.           case 3:
  460.             pcclstore (dirns, nDirns);
  461.             nDirns = 0;
  462.             pccfstore (NCROSSCODE);
  463.  
  464.             dirns[nDirns++] = direction;
  465.             break;
  466.  
  467.           default:
  468.             break;
  469.           }
  470.         }
  471.       }
  472.     }
  473.   }
  474. /* write terminator to storage region */
  475.   pccfstore (NSTOPCODE);
  476.   /* printf ("\nx_max stored = %ld y_max stored = %ld\n", Xmax, Ymax); */
  477.  
  478.   /* printf ("(PCCCODE: max branching number = %d)\n", branchNMax); */
  479.   return (0);
  480. }
  481.  
  482.  
  483. /* PCCTRACK:    function tracks thin lines to produce PCC
  484.  *                usage: nFound = pcctrack (image, &xCenter, 
  485.  *                                    &yCenter, &direction, &branch, &nBranch)
  486.  */
  487.  
  488. #define MOD8(A,B)  ((((A) + (B) - 1) % 8) + 1)
  489.     /* mod 8 addition, where result = [1,8] */
  490.  
  491. #define NPOTD 5                 /* no. potential nbrs in direction of chain */
  492. #define NDIRNS 9                /* no. direction codes */
  493.  
  494. pcctrack (image, xCenter, yCenter, direction, branch, nBranch)
  495.      unsigned char **image;     /* image array */
  496.      long *xCenter,             /* input coord.s of center point */
  497.       *yCenter,                 /* and output coord.s of next point */
  498.       *direction;               /* input and output direction of chain */
  499.      struct branch1 **branch;   /* for branches from current chain */
  500.      long *nBranch;             /* no. of branches in stack */
  501. {
  502.   register long i, dirnIn,      /* incoming direction */
  503.     iDirn,                      /* no. of neighborhood element */
  504.     nFound,                     /* no. ONs in nbrhood; no. 4-conn. groups */
  505.     nNbrs,                      /* no. neighbors to central pixel */
  506.     nAdjacent;                  /* no. of 4-conn pix in group of nbrhood */
  507.   struct point nbrs[NDIRNS];    /* ON pixels neighboring central pixel */
  508.   long nbrDirns[NDIRNS];        /* directions of neighbors */
  509.   struct point ring[NDIRNS];    /* cw ring of potential nbrs around pix */
  510.   long xCenterOld,              /* coord.s of original center pt. */
  511.     yCenterOld, dirnOld;        /* direction into center pixel */
  512.  
  513.   static int dSequence[NDIRNS][NPOTD] =
  514.   {                             /* direction sequence:      */
  515.     {0, 0, 0, 0, 0},
  516.     {5, 7, 3, 6, 4},            /*  neighborhood directions are checked  */
  517.     {7, 5, 6, 8, 4},            /*  in sequence depending on incoming    */
  518.     {7, 1, 5, 8, 6},            /*  direction, so that current chain     */
  519.     {1, 7, 8, 2, 6},            /*  follows straightest line             */
  520.     {1, 3, 7, 2, 8},            /*  e.g. - if incoming direction is 1,   */
  521.     {3, 1, 2, 4, 8},            /*  outgoing direction 5 is checked      */
  522.     {3, 5, 1, 4, 2},            /*  first, then 6, and 4                 */
  523.     {5, 3, 4, 6, 2}
  524.   };
  525.   static int dRing[NDIRNS][NPOTD] =
  526.   {                             /* semi-rings of dirns around pix */
  527.     {0, 0, 0, 0, 0},
  528.     {3, 4, 5, 6, 7},
  529.     {4, 5, 6, 7, 8},
  530.     {5, 6, 7, 8, 1},
  531.     {6, 7, 8, 1, 2},
  532.     {7, 8, 1, 2, 3},
  533.     {8, 1, 2, 3, 4},
  534.     {1, 2, 3, 4, 5},
  535.     {2, 3, 4, 5, 6}
  536.   };
  537.  
  538. /* find coordinates of ring around central pixel in potential directions */
  539.   xCenterOld = *xCenter;
  540.   yCenterOld = *yCenter;
  541.   dirnOld = *direction;
  542.   dirnIn = MOD8 (*direction, 4);
  543.  
  544.   for (i = 0; i < NPOTD; i++) {
  545.     iDirn = dRing[dirnIn][i];
  546.     nbrtoxy (iDirn, xCenterOld, yCenterOld,
  547.              (long *) &(ring[iDirn].x), (long *) &(ring[iDirn].y));
  548.   }
  549.  
  550. /* find all ON or ERASED neighbors in potential directions in dirn priority */
  551.   *direction = 0;
  552.   for (i = 0, nNbrs = 0, nFound = 0; i < NPOTD; i++) {
  553.     iDirn = dSequence[dirnIn][i];
  554.     if (image[ring[iDirn].y][ring[iDirn].x] != IMGOFF) {
  555.       nbrs[nNbrs] = ring[iDirn];
  556.       nbrDirns[nNbrs++] = iDirn;
  557.       if (image[ring[iDirn].y][ring[iDirn].x] == IMGON) {
  558.         if (nFound == 0) {
  559.           *direction = iDirn;
  560.           *xCenter = ring[iDirn].x;
  561.           *yCenter = ring[iDirn].y;
  562.         }
  563.         nFound++;
  564.       }
  565.     }
  566.   }
  567.  
  568. /* if more than one point is found, then find no. of 4-connected groups */
  569.   if (nFound > 0 && nNbrs > 1) {
  570.     nAdjacent = 0;
  571.     for (i = 0, nFound = 0; i < NPOTD; i++) {
  572.       iDirn = dRing[dirnIn][i];
  573.       if (image[ring[iDirn].y][ring[iDirn].x] != IMGOFF) {
  574.         if (nAdjacent == 0)
  575.           nFound++;
  576.         nAdjacent++;
  577.       }
  578.       else
  579.         nAdjacent = 0;
  580.     }
  581.     /* for extra groups beyond branching pixel, push branches */
  582.     for (i = nFound - 1; i > 0; --i) {
  583.       pccbranch (branch, xCenterOld, yCenterOld, dirnOld);
  584.       (*nBranch)++;
  585.     }
  586.   }
  587.  
  588. /* set value to ERASED if it is a feature node */
  589.   if (nFound > 1)
  590.     image[yCenterOld][xCenterOld] = ERASED;
  591. /* if it is not a feature point, and not a break point, set value 
  592.  * to 0 (break point has already been set to ERASED in PCCCODE) */
  593.   else if (image[yCenterOld][xCenterOld] != ERASED)
  594.     image[yCenterOld][xCenterOld] = IMGOFF;
  595.  
  596.   return (nFound);
  597. }
  598.  
  599.  
  600.  
  601.  
  602. /* PCCRSTORE:   function stores feature codes and locations for
  603.  *            start and break (R) features
  604.  *                      usage: pccrstore (feature, xFeature, yFeature)
  605.  *
  606.  */
  607.  
  608. pccrstore (feature, xFeature, yFeature)
  609.      register long feature,     /* feature type */
  610.        xFeature, yFeature;      /* coord.s of feature */
  611. {
  612. /* store feature code and x,y coordinates */
  613.   fcCode[nByteCode++] = code.codeFeat[feature];
  614.  
  615.   fcCode[nByteCode++] = (unsigned char) (xFeature & 0xff);
  616.   fcCode[nByteCode++] = (unsigned char) ((xFeature >> 8) & 0xff);
  617.   fcCode[nByteCode++] = (unsigned char) (yFeature & 0xff);
  618.   fcCode[nByteCode++] = (unsigned char) ((yFeature >> 8) & 0xff);
  619.  
  620.   return (0);
  621. }
  622.  
  623.  
  624. /* PCCLSTORE:   function performs line storage by taking up to 3
  625.  *            direction vectors and storing them as a single
  626.  *              feature chain code
  627.  *                      usage: pcclstore (dirns, nDirns)
  628.  *                              int *dirns;
  629.  *
  630.  */
  631.  
  632. pcclstore (dirns, nDirns)
  633.      long dirns[NDIRNSPERFEATURE];  /* array of dirn.s per feature */
  634.      register long nDirns;      /* no. directions in current feature */
  635. {
  636. /* store feature code */
  637.   switch (nDirns) {
  638.   case 0:
  639.     break;
  640.   case 1:
  641.     fcCode[nByteCode++] = code.code1[dirns[0] - 1];
  642.     break;
  643.   case 2:
  644.     fcCode[nByteCode++] = code.code2[(dirns[0] - 1)
  645.                                      + ((dirns[1] - 1) << 3)];
  646.     break;
  647.   case 3:
  648.     fcCode[nByteCode++] = code.code3[(dirns[0] - 1)
  649.                                      + ((dirns[1] - 1) << 3)
  650.                                      + ((dirns[2] - 1) << 6)];
  651.     break;
  652.   default:
  653.     break;
  654.   }
  655.  
  656.   return (0);
  657. }
  658.  
  659.  
  660. /* PCCFSTORE:   function stores feature codes for non-break PCC features
  661.  *            i.e. those that are not the source of a structure
  662.  *                      usage: pccfstore (feature)
  663.  *
  664.  */
  665.  
  666. pccfstore (feature)
  667.      register long feature;     /* feature type */
  668. {
  669.  
  670. /* store feature code */
  671.   fcCode[nByteCode++] = code.codeFeat[feature];
  672.  
  673.   return (0);
  674. }
  675.  
  676.  
  677. /* PCCWRITE:    function writes PCC code to file
  678.  *                    usage: pccwrite (filename, pcc, nCode, width, height)
  679.  *
  680.  */
  681.  
  682. pccwrite (filename, pcc, nCode, width, height)
  683.      char *filename;
  684.      unsigned char *pcc;        /* PCC code */
  685.      long nCode;                /* no. bytes of code */
  686.      long width, height;        /* image size */
  687. {
  688.   FILE *fpOut;
  689.  
  690. /* open output file */
  691.   if ((fpOut = fopen (filename, "wb")) == NULL) {
  692.     printf ("PCCWRITE: cannot open file", 1);
  693.     return (-1);
  694.   }
  695.  
  696. /* write output header and image */
  697.  
  698.   fprintf (fpOut, "TYPE=%s\n", "PCC");
  699.   fprintf (fpOut, "IMAGE SIZE=%d %d\n", width, height);
  700.   fprintf (fpOut, "PCC LENGTH=%d\n", nByteCode);
  701.   fwrite (fcCode, sizeof (unsigned char), nByteCode, fpOut);
  702.  
  703.   fclose (fpOut);
  704.  
  705.   return (1);
  706. }
  707.